package cn.volunteer.points.system.handle;

import cn.volunteer.points.system.annotation.AdminLoginToken;
import cn.volunteer.points.system.annotation.LoginToken;
import cn.volunteer.points.system.annotation.PassToken;
import cn.volunteer.points.system.mapper.UserMapper;
import cn.volunteer.points.system.pojo.entity.User;
import cn.volunteer.points.system.pojo.qo.LoginQO;
import cn.volunteer.points.system.util.JWTUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @description: 请求拦截器(token校验)
 * @author:
 * @create: 创建时间：2021-04-18
 **/
public class AuthenticationInterceptor implements HandlerInterceptor {
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    @Autowired
    private UserMapper userMapper ;

    @Override
    public boolean preHandle(HttpServletRequest request , HttpServletResponse response , Object object){

        // 1.在请求头中获取token
        String token = request.getHeader("token");

        // 2.校验
        if (!(object instanceof HandlerMethod)) {
            return true ;
        }

        HandlerMethod handlerMethod = (HandlerMethod)object;
        Method method = handlerMethod.getMethod();

        // 3.检查是否有PassToken注解，有就跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }

        // 4.用户token检验
        if (method.isAnnotationPresent(LoginToken.class)) {
            LoginToken loginToken = method.getAnnotation(LoginToken.class);

            if (loginToken.required()) {
                // 1.进行token非空校验
                if (StringUtils.isEmpty(token)) {
                    throw new ServiceException(ServiceErrorCode.TOKEN_INVALID);
                }

                // 2.获取token中的userName进行用户判空
                String userName  ;
                try{
                    Claim claim = JWT.decode(token).getClaim("userName");

                    userName = claim.asString();
                }catch (JWTDecodeException j){
                    throw new ServiceException(ServiceErrorCode.TOKEN_INFO);
                }

                LoginQO find = new LoginQO();
                find.setUserName(userName);
                User user = userMapper.findUserBy(find);
                if (ObjectUtils.isEmpty(user)) {
                    throw new ServiceException(ServiceErrorCode.USER_NO_EXEIT);
                }

                // 3.校验token是否有效
                return JWTUtils.verity(token);

            }
        }

        // 5.管理员token检验
        if (method.isAnnotationPresent(AdminLoginToken.class)) {
            AdminLoginToken adminLoginToken = method.getAnnotation(AdminLoginToken.class);
            if (adminLoginToken.required()) {
                // 1.进行token非空校验
                if (StringUtils.isEmpty(token)) {
                    throw new ServiceException(ServiceErrorCode.TOKEN_INVALID);
                }

                // 2.获取token中的userName进行用户判空
                String userName  ;
                try{
                    Claim claim = JWT.decode(token).getClaim("userName");
                    userName = claim.asString();
                }catch (JWTDecodeException j){
                    throw new ServiceException(ServiceErrorCode.TOKEN_INFO);
                }

                LoginQO find = new LoginQO();
                find.setUserName(userName);
                User user = userMapper.findUserBy(find);
                if (ObjectUtils.isEmpty(user)) {
                    throw new ServiceException(ServiceErrorCode.USER_NO_EXEIT);
                }
                if (!user.getRole().equals(0)) {
                    throw new ServiceException(ServiceErrorCode.ROLE_ERROR);
                }

                // 3.校验token是否有效
                return JWTUtils.verity(token);

            }
        }

        return true ;

    }
}
